#include "../include/MySQLConnector.h"
#include "../include/Configuration.h"
using namespace log4cpp;
MySQLConnector* MySQLConnector::_pinstance = nullptr;
MYSQL * MySQLConnector::_conn = nullptr;
MYSQL_RES * MySQLConnector::_result = nullptr;
mutex MySQLConnector::_mux;
MySQLConnector::MySQLConnector()
{
    //构造函数初始化连接
    _conn = mysql_init(nullptr);
    if(_conn == NULL)
    {
        LOG_ERROR("mysql_init error");
    }
}
MySQLConnector::~MySQLConnector()
{
    if(_conn !=nullptr)
    {
        mysql_close(_conn);
        _conn = nullptr;
    }
    if(_result != nullptr)
    {
        mysql_free_result(_result);
        _result = nullptr;
    }
}
MySQLConnector * MySQLConnector::getInstance()
{
    lock_guard<mutex>lock(_mux);
    if(_pinstance == nullptr)
    {
        _pinstance = new MySQLConnector();
    }
    return _pinstance;
}
MYSQL_RES*  MySQLConnector::getResult()
{
    if(_result != nullptr)
    {
        return _result;
    }
    else
    {
        LOG_ERROR("MYSQL_RES is nullptr");
        return nullptr;
    }
}
void MySQLConnector::destory()
{
    lock_guard<mutex>lock(_mux);
    if(_conn != nullptr)
    {
        mysql_close(_conn);
        _conn = nullptr;
    }
    if(_result != nullptr)
    {
        mysql_free_result(_result);
        _result = nullptr;
    }
    if(_pinstance )
    {
        delete _pinstance;
        _pinstance = nullptr;
    }
}
bool MySQLConnector::hasResult()
{
    return mysql_num_rows(_result) != 0;
}
void MySQLConnector::showResult()
{
    if(!_result)
    {
        LOG_ERROR("sqlresult is null");
        return;
    }

    _field_num = mysql_num_fields(_result);
    cout << "MySQLConnector.cpp 83 showresult(), out print while" << endl;
    while((_row = mysql_fetch_row(_result)))
    {
        cout << "MySQLConnector.cpp 85 showresult(), in print while" << endl;
        for(int i = 0; i < _field_num; ++i)
        {
            printf("%s\t", _row[i] == NULL ? "NULL" : _row[i]);
        }
        printf("\n");
    }
}

bool MySQLConnector::query(const string & sql)
{
    if(!_conn )
    {
        LOG_ERROR("mysqlconn is nullptr");
        return false;
    }
    if(_result)
    {
        mysql_free_result(_result);
    }
    if(mysql_query(_conn, sql.c_str()))
    {
        LOG_ERROR("mysql_query");
        return false;
    }
    _result = mysql_store_result(_conn);
    if(!_result)
    {
        LOG_ERROR("mysql_store_result");
        return false ;
    }
    return true;
}

bool MySQLConnector::connect(const string &localhost,
                             const string &username,
                             const string &password,
                             const string &database)
{
    if(_conn != nullptr)
    {
        if(mysql_real_connect(_conn, localhost.c_str(), username.c_str() , 
                              password.c_str(), database.c_str(),
                              0, NULL, 0) == NULL)
        {
            mysql_close(_conn);
            _conn = nullptr;
            LOG_ERROR("mysql_real_connect");
            return false;
        }

    }
    else
    {
        LOG_ERROR("mysql conn is nullptr");
        return false;
    }
    return true;
}

bool MySQLConnector::execute(const string &sql)
{
    if(!_conn )
    {
        LOG_ERROR("mysql conn is null");
        return false;
    }
    if(_result)
    {
        mysql_free_result(_result);
    }
        if(mysql_query(_conn, sql.c_str()))
        {
            LOG_ERROR("execute error");
            return false;
        }

    return true;
}

string MySQLConnector::getSalt()
{
    showResult();
    if(hasResult() && (mysql_num_rows(_result) == 1))
    {
        mysql_data_seek(_result, 0);
        _row = mysql_fetch_row(_result);
        if(!_row)
        {
            LOG_ERROR("fail fetch row");
            return "";
        }
        _field_num = mysql_num_fields(_result);
        if(_field_num == 0)
        {
            LOG_ERROR("no field in result");
            return "";
        }
        string str;
        char * salt = _row[2];
        if(salt)
        {
            str = salt;
        }
        else
        {
            str = "";
        }
        cout << "MySQLConnector.cpp getsalt() 165 ,salt = " << str << endl;
        return str;
    }
    else
    {
        LOG_WARN("find no result or mutilrows");
        return "";
    }
}

bool MySQLConnector::compareCrypt(const string &username, const string &crypt)
{
    cout << "MySQLConnector.cpp 206, username = " << username << " , crypt = " << crypt << endl;
    LOG_WARN("forbit combining sql string, please conrrect later!!");
    string sql = "select encrypt from user where name = '" + username +"'";
    MySQLConnector* mysqlconn = MySQLConnector::getInstance();
    cout << "MySQLConnector.cpp compareCrypt() << sql = " << sql << endl;
    mysqlconn->query(sql);
    showResult();
    if(hasResult())
    {
        // showResult();
        mysql_data_seek(_result,0);
        _row = mysql_fetch_row(_result);
        if(!_row)
        {
            LOG_INFO("fetch no row");
            return false;
        }
        _field_num = mysql_num_fields(_result);
        cout << "MySQLConnector.cpp compareCrypt() 224, _field_num = " << _field_num << endl;
        if(!_field_num)
        {
            LOG_INFO("has no field");
            return false;
        }
        string crypt_str;
        char * crypt_cstr = _row[0];
        if(crypt_cstr)
        {
            crypt_str = crypt_cstr;
            cout << "MySQLConnector.cpp compareCrypt() 229, crypt = " << crypt << endl;
        }
        else
        {
            LOG_INFO("crypt is null");
            return false;
        }
        //开始比对
        if(crypt == crypt_str)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        LOG_INFO("has no result");
        return false;
    }
}
